package circles;

import classifiers.AbstractDoAction;
import classifiers.CircleClassifier;
import classifiers.IsRepaint;
import draw.ExploringMedics;
import draw.ImageFromArray;
import histogram.HistogramDescr;
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.util.LinkedList;

public class DrawCircles extends AbstractDoAction implements IsRepaint {

    int[][] neiro;
    int[][] origin;
    int[][] binary;
    int[][] marked;
    BufferedImage markImage;

    public DrawCircles(int[][] neiro, int[][] origin, int[][] binary, int[][] marked, BufferedImage markImage) {
        super(marked);
        this.neiro = neiro;
        this.origin = origin;
        this.binary = binary;
        this.marked = marked;
        this.markImage = markImage;
    }

    @Override
    public void doAction(int xStart, int yStart) {

        if (neiro[xStart][yStart] != HistogramDescr.MITAH || binary[xStart][yStart] != ExploringMedics.WHITE) {
            return;
        }

        int curMark = marked[xStart][yStart];

        switch (curMark) {
            case CircleClassifier.CIRCLES:
                repaint(xStart, yStart, CircleClassifier.OVAL, ImageFromArray.ovalColor);
                break;
            case CircleClassifier.OVAL:
                repaint(xStart, yStart, CircleClassifier.NO_MARK, null);
                break;
            default:
                repaint(xStart, yStart, CircleClassifier.CIRCLES, ImageFromArray.circleColor);
                break;
        }

    }

    void repaint(int xStart, int yStart, int nextMark, int nextColor[]) {
        LinkedList<Integer> xQueue = new LinkedList<Integer>();
        LinkedList<Integer> yQueue = new LinkedList<Integer>();

        xQueue.push(xStart);
        yQueue.push(yStart);

        int curMark = marked[xStart][yStart];

        int dx[] = {-1, 1, 0, 0};
        int dy[] = {0, 0, -1, 1};

        while (!xQueue.isEmpty()) {
            int x = xQueue.pop();
            int y = yQueue.pop();

            if (x >= width - 1 || y >= height - 1 || x <= 0 || y <= 0) {
                continue;
            }

            if (binary[x][y] == ExploringMedics.WHITE
                    && marked[x][y] == curMark && neiro[x][y] == HistogramDescr.MITAH) {

                marked[x][y] = nextMark;

                WritableRaster raster = markImage.getRaster();

                int[] sample = {};
                int curVal = origin[x][y];

                if (nextColor != null) {
                    sample = new int[]{(curVal + nextColor[0]) / 2,
                        (curVal + nextColor[1]) / 2,
                        (curVal + nextColor[2]) / 2,
                        ExploringMedics.WHITE};
                } else {
                    sample = new int[]{
                        curVal, curVal, curVal, ExploringMedics.WHITE
                    };
                }

                raster.setPixel(x, y, sample);

                for (int i = 0; i < 4; i++) {
                    xQueue.push(x + dx[i]);
                    yQueue.push(y + dy[i]);
                }
            }
        }
    }

    @Override
    public BufferedImage getImage() {
        return markImage;
    }
}
